package com.moli.iov.common.hbase.service;

import com.moli.iov.common.hbase.dto.create.CreateTableCreateDto;
import com.moli.iov.common.hbase.dto.create.InsertBatchCreateDto;
import com.moli.iov.common.hbase.dto.create.InsertCreateDto;
import com.moli.iov.common.hbase.dto.modify.DeleteBatchRowModifyDto;
import com.moli.iov.common.hbase.dto.modify.DeleteRowModifyDto;
import com.moli.iov.common.hbase.dto.modify.DropTableModifyDto;
import com.moli.iov.common.hbase.dto.modify.TruncateTableModifyDto;
import com.moli.iov.common.hbase.dto.query.*;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.filter.ColumnPaginationFilter;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.PageFilter;
import org.apache.hadoop.hbase.util.Bytes;
import org.springframework.util.StringUtils;


import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName IHbaseService
 * @Description TODO
 * @Author lixy
 * @Date 2019/4/22 11:37
 **/
public interface IHbaseService {

    /**
     * Family column.
     */
    public static byte[] FAMILY = "fm1".getBytes();

    /**
     * Qualifier column.
     */
    public static byte[] QUALIFIER = "messageContent".getBytes();

    /**
     *
     */
    public static final byte[] ZERO = new byte[]{0x00};

    /**
     * Concat to Vehicle shelf number and start date or end date.
     * @param vin Vehicle shelf number.
     * @param date Start date or end date.
     * @return After of concat a byte array.
     */
    default byte[] getRowKey(String vin, Date date) {
        return Bytes.toBytes(vin + "_" + (Long.MAX_VALUE - date.getTime()));
    }

    /**
     * Build a pagination filter of scan.
     * @param rowBounds Pagination of row bounds.
     * @return Build a pagination scan.
     */
    default Scan buildPaginationScan(RowBounds rowBounds){
        Integer offset = rowBounds.getOffset(), limit = rowBounds.getLimit();
        Scan scan = new Scan();
        Filter filter = new ColumnPaginationFilter(limit, offset);
        scan.setFilter(filter);
        scan.addColumn(FAMILY, QUALIFIER);
        return scan;
    }

    /**
     * Build a pagination filter of scan.
     * @param pageSize Pagination of page size.
     * @param reversed Whether reversed.
     * @return Build a pagination scan.
     */
    default Scan buildPaginationScan(int pageSize, Boolean reversed){
        Scan scan = new Scan();
        Filter filter = new PageFilter(pageSize);
        scan.setFilter(filter);
        scan.addColumn(FAMILY, QUALIFIER);
        scan.setCacheBlocks(true);
        scan.setCaching(8000);
        scan.setReversed(reversed);
        return scan;
    }

    /**
     * Build a start row and end row filter of scan.
     * @param startRow Start row.
     * @param stopRow Stop row.
     * @param reversed Whether reversed.
     * @return Build a normal scan.
     */
    default Scan buildScan(String startRow, String stopRow, Boolean reversed){
        Scan scan = new Scan();
        if (!StringUtils.isEmpty(startRow)) {
            scan.setStartRow(Bytes.toBytes(startRow));
        }
        if (!StringUtils.isEmpty(stopRow)) {
            scan.setStopRow(Bytes.toBytes(stopRow));
        }
        scan.addColumn(FAMILY, QUALIFIER);
        scan.setCacheBlocks(true);
        scan.setCaching(8000);
        scan.setReversed(reversed);
        return scan;
    }

    /**
     * According to table name and row prefix and {@link RowBounds} filter of result list.
     * @param tableName Table name.
     * @param rowPrefix Row prefix.
     * @param rowBounds Pagination of row bounds.
     * @return After of Pagination filter result list.
     * @throws Exception {@link NullPointerException} or {@link Exception}.
     */
    List<byte[]> selectList(String tableName, byte[] rowPrefix, RowBounds rowBounds) throws Exception;

    /**
     * According to table name and start row and end row filter of result map.
     * @param tableName Table name.
     * @param startRow Start row.
     * @param stopRow Stop row.
     * @return After of filter result map.
     * @throws Exception {@link NullPointerException} or {@link Exception}.
     */
    Map<String, byte[]> mapRow(String tableName, String startRow, String stopRow) throws Exception;

    /**
     * According to table name and start row and end row filter of result map.
     * @param tableName Table name.
     * @param startRow Start row.
     * @param stopRow Stop row.
     * @param reversed Whether reversed.
     * @return After of filter result map.
     * @throws Exception {@link NullPointerException} or {@link Exception}.
     */
    Map<String, byte[]> mapRow(String tableName, String startRow, String stopRow, Boolean reversed) throws Exception;

    /**
     * According to table name and start row and end row filter of result map.
     * @param tableName Table name.
     * @param pageSize Page size.
     * @return After of filter result map.
     * @throws Exception {@link NullPointerException} or {@link Exception}.
     */
    Map<String, byte[]> mapRow(String tableName, Integer pageSize) throws Exception;

    /**
     * According to table name and start row and end row filter of result map.
     * @param tableName Table name.
     * @param pageSize Page size.
     * @param reversed Whether reversed.
     * @return After of filter result map.
     * @throws Exception {@link NullPointerException} or {@link Exception}.
     */
    Map<String, byte[]> mapRow(String tableName, Integer pageSize, Boolean reversed) throws Exception;

    /**
     * According to table name and start row and stop row and {@link RowBounds} filter of result list.
     * @param tableName Table name.
     * @param startRow Start row.
     * @param stopRow Stop row.
     * @param rowBounds Pagination of row bounds.
     * @return After of Pagination filter result list.
     * @throws Exception {@link NullPointerException} or {@link Exception}.
     */
    List<byte[]> selectList(String tableName, byte[] startRow, byte[] stopRow, RowBounds rowBounds) throws Exception;

    /**
     * According to row key and table name filter of single result.
     * @param tableName Table name.
     * @param rowKey Row key.
     * @return After of filter single result.
     * @throws Exception {@link NullPointerException} or {@link Exception}.
     */
    byte[] selectOne(String tableName, String rowKey) throws Exception;

    /**
     * 插入数据
     * @param insertCreateDto
     * @throws Exception
     */
    Boolean insertData(InsertCreateDto insertCreateDto) throws Exception;

    /**
     * 批量插入数据
     * @param insertBatchCreateDto
     * @throws Exception
     */
    Boolean insertBatchData(InsertBatchCreateDto insertBatchCreateDto) throws Exception;

    /**
     * 创建表
     * @param createTableCreateDto
     * @throws Exception
     */
    Boolean createTable(CreateTableCreateDto createTableCreateDto) throws Exception;

    /**
     * 清空表
     * @param truncateTableModifyDto
     * @throws Exception
     */
    Boolean truncateTable(TruncateTableModifyDto truncateTableModifyDto) throws Exception;

    /**
     * 删除表
     * @param dropTableModifyDto
     * @throws Exception
     */
    Boolean dropTable(DropTableModifyDto dropTableModifyDto) throws Exception;

    /**
     * 删除表中一行
     * @param deleteRowModifyDto
     * @throws Exception
     */
    Boolean deleteRow(DeleteRowModifyDto deleteRowModifyDto) throws Exception;

    /**
     * 批量删除 数据
     * @param deleteBatchRowModifyDto
     * @throws Exception
     */
    Boolean deleteBatchRow(DeleteBatchRowModifyDto deleteBatchRowModifyDto) throws Exception;

    /**
     * 根据key查询
     * @param queryRowQueDto
     * @throws Exception
     */
    Boolean queryRow(QueryRowQueDto queryRowQueDto) throws Exception;

    /**
     * 扫描表
     * @param getResultScannerQueDto
     * @return
     * @throws Exception
     */
    HashMap<String,byte[]> getResultScanner(GetResultScannerQueDto getResultScannerQueDto) throws Exception;

    List<byte[]> getDataResult(GetResultScanner resultScanner) throws Exception;

    List<byte[]> getDataResult(String startRow, String endRow, String tableName) throws Exception;

    /**
     * 统计表的记录条数
     * @param countQueDto
     * @return
     * @throws Exception
     */
    Integer count(CountQueDto countQueDto) throws Exception;

    /**
     * 主键模糊查询统计
     * @param queryResultQueDto
     * @return
     * @throws Exception
     */
    HashMap<String,byte[]> queryResult(QueryResultQueDto queryResultQueDto) throws Exception;
}
